use super::error::Error::{self, *};
use axum::response::{IntoResponse, Response};
use serde::Serialize;

/// 统一的返回类型
#[derive(Serialize, Debug, Clone)]
pub struct R<T: Serialize = ()> {
    code: u8,
    message: String,
    data: Option<T>,
}

impl<T: Serialize> R<T> {
    /// 返回业务失败信息
    pub fn fail<M: AsRef<str>>(message: M) -> Self {
        let message = String::from(message.as_ref());
        R {
            code: 1,
            data: None,
            message,
        }
    }

    /// 返回登录失效信息
    pub fn token_fail() -> Self {
        R {
            code: 2,
            data: None,
            message: "登录失效，请重新登录".to_string(),
        }
    }

    /// 返回无 data 的成功信息
    pub fn ok() -> Self {
        R {
            code: 0,
            data: None,
            message: "操作成功".to_string(),
        }
    }

    /// 返回有 data 的成功信息
    pub fn success(data: T) -> Self {
        R {
            code: 0,
            data: Some(data),
            message: "操作成功".to_string(),
        }
    }
}

/// 为 [R<T>] 实现 [IntoResponse] trait
impl<T: Serialize> IntoResponse for R<T> {
    fn into_response(self) -> Response {
        axum::Json(self).into_response()
    }
}

/// 将自定义的[Error]转成 [R]
impl<T: Serialize> From<Error> for R<T> {
    fn from(e: Error) -> Self {
        match e {
            Business(e) => R::fail(e),
            Token => R::token_fail(),
            Path(_) | Query(_) | Json(_) => R::fail(e.to_string()),
            Validation(e) => R::fail(e),
        }
    }
}

/// 将自定义的[Error]转成 [R]
impl<T: Serialize> From<Result<T, Error>> for R<T> {
    fn from(res: Result<T, Error>) -> Self {
        match res {
            Ok(data) => R::success(data),
            Err(e) => e.into(),
        }
    }
}


/// 将自定义的[anyhow::Error]转成 [R]
impl<T: Serialize> From<Result<T, anyhow::Error>> for R<T> {
    fn from(res: Result<T, anyhow::Error>) -> Self {
        match res {
            Ok(data) => R::success(data),
            Err(e) => Error::from(e).into(),
        }
    }
}
